﻿using LvcChong.DB;
using Mapster;
using MapsterMapper;
using RestSharp;
using System.ComponentModel;

namespace LvcChong
{
    public partial class FormOrderQuery : Form
    {
        private OrderQueryRepository _repository;
        private BindingList<OrderQueryOutput> _source = new BindingList<OrderQueryOutput>();
        private LayerHelper _layerHelper = new LayerHelper();

        public FormOrderQuery()
        {
            InitializeComponent();
            _repository = new OrderQueryRepository();

            pager.OnPageChanged += Pagination_OnPageChanged;
            pager.OnPageSizeChanged += Pager_OnPageSizeChanged;

            InitGridLayout();

            InitData();
        }

        private void Pager_OnPageSizeChanged(object? sender, EventArgs e)
        {
            pager.Tag = null;
        }

        private void Pagination_OnPageChanged(object? sender, EventArgs e)
        {
            RefreshData();
        }

        private void InitGridLayout()
        {
            grid.InitializeRow += (s, e) =>
            {
                var item = e.Row.ListObject as OrderQueryOutput;
                if (item == null) return;

                if (item.actualTime == null) e.Row.Cells[nameof(OrderQueryOutput.actualTime)].Value = "未结束";
                if (item.actualElectricQuantity == null) e.Row.Cells[nameof(OrderQueryOutput.actualTime)].Value = "未上报";

                if (item.inTime.ParseToLong(0) != 0)
                {
                    var time = item.inTime.ParseToLong().ToDateTimeFromMilliseconds();
                    if (time != null)
                        e.Row.Cells[nameof(OrderQueryOutput.inTime)].Value = time.Value.ToString("yyyy-MM-dd HH:mm:ss");
                }

                if (item.updateTime.ParseToLong(0) != 0)
                {
                    var time = item.updateTime.ParseToLong().ToDateTimeFromMilliseconds();
                    if (time != null)
                        e.Row.Cells[nameof(OrderQueryOutput.updateTime)].Value = time.Value.ToString("yyyy-MM-dd HH:mm:ss");
                }
            };

            grid.ClickCell += (s, e) =>
            {
                if (e.Cell.Column.Key == nameof(OrderQueryOutput.userId))
                {
                    if (opSwitch.CheckedItem.DataValue.ParseToInt() == 0)
                        new FormUserOrderQuery(e.Cell.Value.ToString()).ShowDialog();
                    else new FormUserQuery(e.Cell.Value.ToString()).ShowDialog();
                }
                else if (e.Cell.Column.Key == nameof(OrderQueryOutput.licenseNum))
                {
                    new FormVehicleQuery(e.Cell.Value?.ToString(), ValueType.LicenseNum).ShowDialog();
                }
                else if (e.Cell.Column.Key == nameof(OrderQueryOutput.vinNum))
                {
                    new FormVehicleQuery(e.Cell.Value?.ToString(), ValueType.VIN).ShowDialog();
                }
            };

            var displayCol = new List<UltraGridDisplayItem> {
                new UltraGridDisplayItem{ Key=nameof(OrderQueryOutput.orderNum), Caption="订单号", Position=2,ColumnWidth =200},
                new UltraGridDisplayItem{ Key=nameof(OrderQueryOutput.orderType), Caption="订单类型", Position=2,ColumnWidth =120},
                new UltraGridDisplayItem{ Key=nameof(OrderQueryOutput.userId), Caption="用户编号", Position=2,ColumnWidth =120},
                new UltraGridDisplayItem{ Key=nameof(OrderQueryOutput.userPhone), Caption="手机号", Position=2,ColumnWidth =120},
                new UltraGridDisplayItem{ Key=nameof(OrderQueryOutput.licenseNum), Caption="车牌号", Position=2,ColumnWidth =100},
                new UltraGridDisplayItem{ Key=nameof(OrderQueryOutput.vinNum), Caption="VIN", Position=2,ColumnWidth =180},
                new UltraGridDisplayItem{ Key=nameof(OrderQueryOutput.estateName), Caption="小区名称", Position=2,ColumnWidth =180},
                new UltraGridDisplayItem{ Key=nameof(OrderQueryOutput.deviceName), Caption="设备机号", Position=5,ColumnWidth =120},
                new UltraGridDisplayItem{ Key=nameof(OrderQueryOutput.portNum), Caption="插座", Position=5,ColumnWidth =100},
                new UltraGridDisplayItem{ Key=nameof(OrderQueryOutput.payPrice), Caption="消费金额", Position=5,ColumnWidth =100},
                new UltraGridDisplayItem{ Key=nameof(OrderQueryOutput.totalElectricMoney), Caption="电费", Position=5,ColumnWidth =100},
                new UltraGridDisplayItem{ Key=nameof(OrderQueryOutput.totalServiceFee), Caption="服务费", Position=5,ColumnWidth =100},
                new UltraGridDisplayItem{ Key=nameof(OrderQueryOutput.payWay), Caption="支付方式", Position=5,ColumnWidth =120},
                new UltraGridDisplayItem{ Key=nameof(OrderQueryOutput.isCount), Caption="交易状态", Position=5,ColumnWidth =120},
                new UltraGridDisplayItem{ Key=nameof(OrderQueryOutput.status), Caption="充电状态", Position=5,ColumnWidth =150},
                new UltraGridDisplayItem{ Key=nameof(OrderQueryOutput.paymentPrice), Caption="工作时长(分钟/度/元)", Position=5,ColumnWidth =100},
                new UltraGridDisplayItem{ Key=nameof(OrderQueryOutput.actualTime), Caption="实际时长(分钟)", Position=5,ColumnWidth =100}, //actualTime == null 未结束
                new UltraGridDisplayItem{ Key=nameof(OrderQueryOutput.actualElectricQuantity), Caption="实际耗电(度)", Position=5,ColumnWidth =100}, // actualElectricQuantity == null 未上报
                new UltraGridDisplayItem{ Key=nameof(OrderQueryOutput.inTime), Caption="创建时间", Position=5,ColumnWidth =180},
                new UltraGridDisplayItem{ Key=nameof(OrderQueryOutput.updateTime), Caption="更新时间", Position=5,ColumnWidth =180},
                new UltraGridDisplayItem{ Key=nameof(OrderQueryOutput.endType), Caption="结束原因", Position=5,ColumnWidth =180},
            };

            grid.SetDataBinding(_source, null);
            UltraGridHelper.InitializeUltraGridDisplay(grid, displayCol, true, new UltraGridOptions
            {
                EnableFixedHeader = true,
                EnableExport = true,
                ShowSummary = false,
                EnableFilter = true,
            });

            grid.DisplayLayout.NoDataSourceMessageEnabled = Infragistics.Win.DefaultableBoolean.False;
            grid.DisplayLayout.AutoFitStyle = Infragistics.Win.UltraWinGrid.AutoFitStyle.None;

            grid.DisplayLayout.Bands[0].Columns[nameof(OrderQueryOutput.orderType)].SetColumnValueList(ValueListAssist.EnumToValueList(typeof(OrderType)));
            grid.DisplayLayout.Bands[0].Columns[nameof(OrderQueryOutput.payWay)].SetColumnValueList(ValueListAssist.EnumToValueList(typeof(PayWay)));
            grid.DisplayLayout.Bands[0].Columns[nameof(OrderQueryOutput.isCount)].SetColumnValueList(ValueListAssist.EnumToValueList(typeof(OrderStatus)));
            grid.DisplayLayout.Bands[0].Columns[nameof(OrderQueryOutput.status)].SetColumnValueList(ValueListAssist.EnumToValueList(typeof(StatusType)));
            grid.DisplayLayout.Bands[0].Columns[nameof(OrderQueryOutput.endType)].SetColumnValueList(ValueListAssist.EnumToValueList(typeof(EndType)));

            grid.DisplayLayout.Bands[0].Columns[nameof(OrderQueryOutput.userId)].Style = Infragistics.Win.UltraWinGrid.ColumnStyle.URL;
            grid.DisplayLayout.Bands[0].Columns[nameof(OrderQueryOutput.licenseNum)].Style = Infragistics.Win.UltraWinGrid.ColumnStyle.URL;
            grid.DisplayLayout.Bands[0].Columns[nameof(OrderQueryOutput.vinNum)].Style = Infragistics.Win.UltraWinGrid.ColumnStyle.URL;

            grid.DisplayLayout.Bands[0].Columns[nameof(OrderQueryOutput.inTime)].Header.Fixed = true;
            grid.DisplayLayout.Bands[0].Columns[nameof(OrderQueryOutput.inTime)].Header.FixOnRight = Infragistics.Win.DefaultableBoolean.True;
            grid.DisplayLayout.Bands[0].Columns[nameof(OrderQueryOutput.updateTime)].Header.Fixed = true;
            grid.DisplayLayout.Bands[0].Columns[nameof(OrderQueryOutput.updateTime)].Header.FixOnRight = Infragistics.Win.DefaultableBoolean.True;

            grid.DisplayLayout.Override.RowAlternateAppearance.BackColor = Color.FromArgb(244, 244, 244);

            grid.DisplayLayout.Bands[0].SetDefaultBrandSummaryStyle();
            grid.DisplayLayout.Bands[0].AddSummary(
                Infragistics.Win.UltraWinGrid.SummaryType.Count,
                grid.DisplayLayout.Bands[0].Columns[nameof(OrderQueryOutput.orderNum)],
                 Infragistics.Win.UltraWinGrid.SummaryPosition.UseSummaryPositionColumn,
                 "总数 = {0}"
                );

            grid.DisplayLayout.Bands[0].AddSummary(
                Infragistics.Win.UltraWinGrid.SummaryType.Sum,
                grid.DisplayLayout.Bands[0].Columns[nameof(OrderQueryOutput.payPrice)],
                 Infragistics.Win.UltraWinGrid.SummaryPosition.UseSummaryPositionColumn,
                 "{0:#0.00}"
                );

            grid.DisplayLayout.Bands[0].AddSummary(
                Infragistics.Win.UltraWinGrid.SummaryType.Sum,
                grid.DisplayLayout.Bands[0].Columns[nameof(OrderQueryOutput.totalElectricMoney)],
                 Infragistics.Win.UltraWinGrid.SummaryPosition.UseSummaryPositionColumn,
                 "{0:#0.00}"
                );

            grid.DisplayLayout.Bands[0].AddSummary(
                Infragistics.Win.UltraWinGrid.SummaryType.Sum,
                grid.DisplayLayout.Bands[0].Columns[nameof(OrderQueryOutput.totalServiceFee)],
                 Infragistics.Win.UltraWinGrid.SummaryPosition.UseSummaryPositionColumn,
                 "{0:#0.00}"
                );

            grid.DisplayLayout.Bands[0].AddSummary(
                Infragistics.Win.UltraWinGrid.SummaryType.Sum,
                grid.DisplayLayout.Bands[0].Columns[nameof(OrderQueryOutput.paymentPrice)],
                 Infragistics.Win.UltraWinGrid.SummaryPosition.UseSummaryPositionColumn,
                 "{0:#0}.00"
                );

            grid.DisplayLayout.Bands[0].AddSummary(
                Infragistics.Win.UltraWinGrid.SummaryType.Sum,
                grid.DisplayLayout.Bands[0].Columns[nameof(OrderQueryOutput.actualTime)],
                 Infragistics.Win.UltraWinGrid.SummaryPosition.UseSummaryPositionColumn,
                 "{0:#0.00}"
                );

            grid.DisplayLayout.Bands[0].AddSummary(
                Infragistics.Win.UltraWinGrid.SummaryType.Sum,
                grid.DisplayLayout.Bands[0].Columns[nameof(OrderQueryOutput.actualElectricQuantity)],
                 Infragistics.Win.UltraWinGrid.SummaryPosition.UseSummaryPositionColumn,
                 "{0:#0.00}"
                );
        }

        private void InitData()
        {
            cboIsCount.SetDataSource(typeof(OrderStatus).EnumToNameValues(true), "Caption");
            cboIsCount.SelectedIndex = 0;
            cboStatus.SetDataSource(typeof(StatusType).EnumToNameValues(true), "Caption");
            cboStatus.SelectedIndex = 0;
            dtStart.Value = DateTime.Now.GetFirstDayOfMonth();
            dtEnd.Value = DateTime.Now.GetLastDayOfMonth();

            opSwitch.CheckedIndex = 0;
        }

        private void btnQuery_Click(object sender, EventArgs e)
        {
            RefreshData();
        }

        private async void RefreshData()
        {
            var ret = await LayerRefreshAsync(() =>

                GlobalContext.DataProvider.OrderQuery(new OrderQueryInput
                {
                    page = pager.CurrentPageNo,
                    limit = pager.PageSize,
                    fromPage = pager.CurrentPageNo - 1 <= 0 ? null : pager.CurrentPageNo - 1,
                    leastTotal = pager.TotalRecords == 0 ? null : pager.TotalRecords,
                    deepPageTokenArr = pager.Tag?.ToString(),
                    isCount = ((int?)((OrderStatus?)cboIsCount.SelectedItem.DataValue))?.ToString(),
                    status = ((int?)((StatusType?)cboStatus.SelectedItem.DataValue))?.ToString(),
                    dateRange = $"{dtStart.DateTime.ToString("yyyy-MM-01")} ~ {dtEnd.DateTime.ToString("yyyy-MM-dd")}"
                })
            );
            _source.Clear();
            if (ret != null && ret.Data != null)
            {
                if (pager.Tag == null)
                    pager.Tag = ret.OtherMap?.deepPageToken;
                else pager.Tag = pager.Tag + "," + ret.OtherMap?.deepPageToken;

                pager.RefreshPageData(ret.Count);
                foreach (var item in ret.Data) _source.Add(item);

                if (chkSaveDB.Checked) SaveToDB(ret.Data);
            }
        }

        private DateTime? ParseToDateTime(string timeStr)
        {
            return timeStr.ParseToLong().ToDateTimeFromMilliseconds();
        }

        private async void SaveToDB(List<OrderQueryOutput> source)
        {
            var config = new TypeAdapterConfig();
            //映射规则
            config.ForType<OrderQueryOutput, OrderQueryEntity>()
                .Map(dest => dest.orderTypeName, src => ValueListAssist.EnumValueToZhCN(typeof(OrderType), src.orderType))
                .Map(dest => dest.payWayName, src => ValueListAssist.EnumValueToZhCN(typeof(PayWay), src.payWay))
                .Map(dest => dest.isCountName, src => ValueListAssist.EnumValueToZhCN(typeof(OrderStatus), src.isCount))
                .Map(dest => dest.statusName, src => ValueListAssist.EnumValueToZhCN(typeof(StatusType), src.status))
                .Map(dest => dest.endTypeName, src => ValueListAssist.EnumValueToZhCN(typeof(EndType), src.endType))
                .Map(dest => dest.dataCreateTime, src => DateTime.Now)
                .Map(dest => dest.inTime, src => ParseToDateTime(src.inTime))
                .Map(dest => dest.updateTime, src => ParseToDateTime(src.updateTime));
            var mapper = new Mapper(config);//务必将mapper设为单实例
            var dto = mapper.Map<List<OrderQueryEntity>>(source);

            if (dto != null && dto.Count > 0)
            {
                var orderIds = dto.Select(x => x.orderNum).ToList();
                var delRet = await _repository.AsDeleteable().Where(x => orderIds.Contains(x.orderNum)).ExecuteCommandAsync();
                var ret = await _repository.AsInsertable(dto).ExecuteCommandAsync();
                lblInfo.UpdateUI(async () =>
                {
                    lblInfo.Text = $"新增入库{ret-delRet}条, 刷新{delRet}条";
                    await Task.Delay(5 * 1000);
                    lblInfo.Text = ""; 
                });
            }
        }

        private void btnReset_Click(object sender, EventArgs e)
        {
            cboIsCount.SelectedIndex = 0;
            cboStatus.SelectedIndex = 0;
            dtStart.Value = DateTime.Now.GetFirstDayOfMonth();
            dtEnd.Value = DateTime.Now.GetLastDayOfMonth();
        }

        private Task<T> LayerRefreshAsync<T>(Func<T> action)
        {
            var ret = Task.Run(() =>
            {
                try
                {
                    plQuery.UpdateUI(() => plQuery.Enabled = false);
                    _layerHelper.ShowOpaqueLayer(plGrid, 30);
                    return action();
                }
                finally
                {
                    _layerHelper.HideOpaqueLayer();
                    plQuery.UpdateUI(() => plQuery.Enabled = true);
                }
            });
            return ret;
        }
    }
}